import { applyDecorators, Type } from '@nestjs/common';
import {
  ApiExtraModels,
  ApiOkResponse,
  ApiProperty,
  getSchemaPath,
} from '@nestjs/swagger';
import { isObject } from 'class-validator';

export class ResponseDto<T> {
  readonly data: T;

  @ApiProperty()
  readonly code: number;

  @ApiProperty()
  readonly msg: string;

  constructor(res: any) {
    if (typeof res !== 'object' && typeof res !== 'string' && res !== null) {
      res = {};
    }

    if (typeof res === 'string') {
      res = {
        code: 200,
        data: null,
        msg: res,
      };
    }
    // 解构属性，设置默认值
    const { code, data, msg = 'success' } = res;
    console.log(res, ' isObject(data)');

    // 设置属性值
    this.code = code || 200;
    this.data = res.hasOwnProperty('data') ? data : res;
    this.msg = msg || 'success';
  }

  static success({ code, data, msg = 'success' }: any) {
    return new ResponseDto({ code: 200, data, msg });
  }
  static error({ code, data, msg = 'success' }: any) {
    return new ResponseDto({ code: 400, data, msg });
  }
}

export class Pagination {
  @ApiProperty()
  total: number;

  @ApiProperty()
  pageNo: number;

  @ApiProperty()
  pageSize: number;
}

export class PaginatedResponseDto<T> {
  @ApiProperty({ required: false })
  code?: number;
  @ApiProperty({ required: false })
  msg?: string;
  data: {
    records: Array<Partial<T>>;
    pageSize: number;
    pageNo: number;
    total: number;
  };
}
export const ApiResponse = <
  DataDto extends Type<unknown>,
  WrapperDataDto extends Type<unknown>,
>(
  dataDto: DataDto,
  wrapperDataDto: WrapperDataDto,
) =>
  applyDecorators(
    ApiExtraModels(wrapperDataDto, dataDto),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(wrapperDataDto) },
          {
            properties: {
              data: { $ref: getSchemaPath(dataDto) },
            },
          },
        ],
      },
    }),
  );

export const ApiOkResponseData = <DataDto extends Type<unknown>>(
  dataDto: DataDto,
) => ApiResponse(dataDto, ResponseDto);

export const ApiOkResponsePaginated = <DataDto extends Type<unknown>>(
  dataDto: DataDto,
) => ApiResponse(dataDto, PaginatedResponseDto);
